package com.kingdee.hackson.service.impl;

import com.kingdee.hackson.dto.lc.PositionID;
import com.kingdee.hackson.dto.lc.Response;
import com.kingdee.hackson.entity.Position;
import com.kingdee.hackson.service.IInitOrgIdService;
import com.kingdee.hackson.service.ILCService;
import com.kingdee.hackson.utils.PageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

@Service
public class LCServiceImpl implements ILCService {
    private static final Logger LOGGER = LoggerFactory.getLogger(LCServiceImpl.class);
    @Resource
    private CacheManager cacheManager;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private IInitOrgIdService idService;

    public Response query() {
        //Map<Long, Object> map = initMap();
        Map<Long, Object> map = initMapByInitCapacity();
        List<PositionID> positionIDS = quryAllPosition();
        positionIDS = filterByparallelStream(positionIDS, map);
        //positionIDS = filterPositionBySingle(positionIDS, map);
        int total = positionIDS.size();
        positionIDS = PageUtil.startPage(positionIDS, 1, 20);
        List<Position> positions = quryPositionByPage(positionIDS);
        return new Response(total, positions.size(), positions);
    }

    // 40万岗位。占用12.8M内存。Long(long 8字节+long 8字节+对象头16字节)
    private List<PositionID> quryAllPosition() {
        long start1 = System.currentTimeMillis();
        List<PositionID> query = jdbcTemplate.query("select fid,FADMINORGID from t_hbpm_position", new RowMapper<PositionID>() {
            @Override
            public PositionID mapRow(ResultSet resultSet, int i) throws SQLException {
                PositionID positionID = new PositionID();
                positionID.setId(resultSet.getLong(1));
                positionID.setOrgId(resultSet.getLong(2));
                return positionID;
            }
        });
        LOGGER.info("查询所有（岗位ID,组织ID）结果耗时：" + (System.currentTimeMillis() - start1) + " count=" + query.size());
        return query;
    }

    private List<Position> quryPositionByPage(List<PositionID> positionIDS) {
        long start1 = System.currentTimeMillis();
        StringBuilder builder = new StringBuilder("select fid,fjobscmid,fnumber,fNAME,FADMINORGID,FPARENTID,FPOSITIONTYPEID,FJOBID,FTYPEID,FISLEADER,FISSENSITIVE, FPROATTRID,FLOWJOBLEVELID,FHIGHJOBLEVELID,FLOWJOBGRADEID,FHIGHJOBGRADEID,FSTATUS,FENABLE,FDISABLERID,FDISABLEDATE,FCREATORID,FCREATETIME,FMODIFIERID,FMODIFYTIME,fworkplaceid,fdepcytypeid  from t_hbpm_position where fid in (");
        positionIDS.forEach(x -> {
            builder.append(x.getId()).append(",");
        });
        String sql = builder.substring(0, builder.length() - 1);
        sql = sql + ")";
        List<Position> query = jdbcTemplate.query(sql, new RowMapper<Position>() {
            @Override
            public Position mapRow(ResultSet resultSet, int i) throws SQLException {
                Position position = new Position();
                position.setFid(resultSet.getLong(1));
                position.setJobscmid(resultSet.getLong(2));
                position.setNumber(resultSet.getString(3));
                position.setNAME(resultSet.getString(4));
                position.setADMINORGID(resultSet.getLong(5));
                position.setFPARENTID(resultSet.getLong(6));
                position.setFPOSITIONTYPEID(resultSet.getLong(7));
                position.setFJOBID(resultSet.getLong(8));
                position.setFTYPEID(resultSet.getLong(9));
                position.setFISLEADER(resultSet.getString(10));
                position.setFISSENSITIVE(resultSet.getString(11));
                position.setFPROATTRID(resultSet.getLong(12));
                position.setFLOWJOBLEVELID(resultSet.getLong(13));
                position.setFHIGHJOBLEVELID(resultSet.getLong(14));
                position.setFLOWJOBGRADEID(resultSet.getLong(15));
                position.setFHIGHJOBGRADEID(resultSet.getLong(16));
                position.setFSTATUS(resultSet.getString(17));
                position.setFENABLE(resultSet.getString(18));
                position.setFDISABLERID(resultSet.getLong(19));
                position.setFDISABLEDATE(resultSet.getDate(20));
                position.setFCREATORID(resultSet.getLong(21));
                position.setFCREATETIME(resultSet.getDate(22));
                position.setFMODIFIERID(resultSet.getLong(23));
                position.setFMODIFYTIME(resultSet.getDate(24));
                position.setFworkplaceid(resultSet.getLong(25));
                position.setFdepcytypeid(resultSet.getLong(26));

                return position;
            }
        });
        LOGGER.info("查询分页后岗位集合耗时：" + (System.currentTimeMillis() - start1));
        return query;
    }

    /**
     * 建立有权限组织的哈希索引。默认大小方案
     * 1、5.6w下级组织 占用0.4M内存
     * 2、5并发请求。单个耗时5毫秒
     * @return
     */
    private Map<Long, Object> initMap() {
        List<Long> hasrightOrgId = idService.getHasrightOrgId();
        long start = System.currentTimeMillis();
        Map<Long, Object> map = new HashMap<>();
        hasrightOrgId.forEach(x -> {
            map.put(x, null);
        });
        LOGGER.info("初始化Map(默认大小)耗时：" + (System.currentTimeMillis() - start) + " count=" + hasrightOrgId.size());
        hasrightOrgId = null;//及时释放引用，等待下次垃圾回收
        return map;
    }
    /**
     * 建立有权限组织的哈希索引。避免扩容方式
     * 1、5.6w下级组织 占用0.4M内存
     * 2、5并发请求。单个耗时2-3毫秒
     * @return
     */
    private Map<Long, Object> initMapByInitCapacity() {
        List<Long> hasrightOrgId = idService.getHasrightOrgId();
        long start = System.currentTimeMillis();
        int initCapacity = 1 + (int) (hasrightOrgId.size() / 0.75);//避免扩容操作
        Map<Long, Object> map = new HashMap<>(initCapacity);
        hasrightOrgId.forEach(x -> {
            map.put(x, null);
        });
        LOGGER.info("初始化Map(避免扩容)耗时：" + (System.currentTimeMillis() - start) + " count=" + hasrightOrgId.size());
        hasrightOrgId = null;//及时释放引用，等待下次垃圾回收
        return map;
    }

    /**
     * 单线程方式。过滤符合条件的岗位。
     * 1、40w岗位，5并发请求。8线程并行。单个耗时19秒
     * @param positionIDS
     * @param map
     * @return
     */
    private List<PositionID> filterPositionBySingle(List<PositionID> positionIDS, Map<Long, Object> map) {
        long start1 = System.currentTimeMillis();
        Iterator<PositionID> items = positionIDS.iterator();
        while (items.hasNext()) {
            PositionID item = items.next();
            if (map.containsKey(item.getOrgId())) {
                items.remove();
            }
        }
        LOGGER.info("判断符合权限组织岗位集合(单线程)耗时：" + (System.currentTimeMillis() - start1));
        return positionIDS;
    }

    /**
     * 通过多线程方式。过滤符合条件的岗位。
     * 1、40w岗位，5并发请求。8线程并行。单个耗时16毫秒
     * @param positionIDS
     * @param map
     * @return
     */
    private List<PositionID> filterByparallelStream(List<PositionID> positionIDS, Map<Long, Object> map) {
        long start1 = System.currentTimeMillis();
        List<PositionID> filterPositionIDS = new LinkedList<>();
        //Map<Long,Object> threadIds=new HashMap<>(10);
        positionIDS.parallelStream().forEach(x -> {
           /* if(!threadIds.containsKey(Thread.currentThread().getId())){
                threadIds.put(Thread.currentThread().getId(),null);
            }*/
            if (map.containsKey(x.getOrgId())) {
                filterPositionIDS.add(x);
            }
        });
        positionIDS=null;//及时释放引用，等待下次垃圾回收
       // LOGGER.info("filterByparallelStream线程数="+threadIds.size());
        LOGGER.info("判断符合权限组织岗位集合(多线程)耗时：" + (System.currentTimeMillis() - start1));
        return filterPositionIDS;
    }
}
